package com.xu.ai.chatclient.controller;

import java.util.List;
import java.util.Map;

import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import reactor.core.publisher.Flux;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.rag.advisor.RetrievalAugmentationAdvisor;
import org.springframework.ai.rag.retrieval.search.VectorStoreDocumentRetriever;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.xu.ai.chatclient.advisor.ReasoningContentAdvisor;
import com.xu.ai.chatclient.prompt.SystemPrompt;
import com.xu.ai.chatclient.tools.DateTimeTool;
import com.xu.ai.chatclient.tools.ITool;

/**
 * 聊天客户端ChatClient controller
 *
 * @author xuguan
 * @since 2025/9/15
 */
@RestController
@RequestMapping("/api/chat")
public class ChatClientController {

	private final ChatClient chatClient;

	private final ChatMemory chatMemory;

	private final VectorStore vectorStore;

	private final ITool dateTimeTool;

	public ChatClientController(ChatClient.Builder chatClientBuilder, ChatMemory chatMemory, VectorStore vectorStore) {
		this.chatClient = chatClientBuilder.defaultSystem(SystemPrompt.DEFAULT_CHAT_SYSTEM.getTemplate())
			.defaultAdvisors(SimpleLoggerAdvisor.builder().build())
			.build();
		this.chatMemory = chatMemory;
		this.vectorStore = vectorStore;
		this.dateTimeTool = new DateTimeTool();
	}

	@GetMapping(path = "/call-content")
	public String callContent(@RequestParam(value = "userInput", defaultValue = "你是谁?") String userInput) {
		return this.chatClient.prompt().user(userInput).call().content();
	}

	@GetMapping(path = "/stream-content", produces = "text/html;charset=UTF-8")
	public Flux<String> streamContent(@RequestParam(value = "userInput", defaultValue = "你是谁?") String userInput) {
		return this.chatClient.prompt().user(userInput).stream().content();
	}

	@GetMapping(path = "/choose-model-chat", produces = "text/html;charset=UTF-8")
	public Flux<String> chooseModelChat(@RequestParam(value = "userInput", defaultValue = "你是谁?") String userInput,
			@RequestParam(value = "model", defaultValue = "qwen-plus") String model) {
		return this.chatClient.prompt()
			.user(userInput)
			.options(DashScopeChatOptions.builder().withModel(model).build())
			.stream()
			.content();
	}

	@GetMapping(path = "/deep-thinking", produces = "text/html;charset=utf-8")
	public Flux<String> deepThinking() {
		return this.chatClient.prompt()
			.options(DashScopeChatOptions.builder()
				.withModel(DashScopeApi.ChatModel.QWEN_PLUS.getModel())
				.withEnableThinking(Boolean.TRUE)
				.withStream(Boolean.TRUE)
				.build())
			.advisors(new ReasoningContentAdvisor())
			.user("给我讲一个生动的故事, 结合安徒生童话, 请思考后再回答")
			.stream()
			.content();
	}

	@GetMapping(path = "/choose-model-thinking", produces = "text/html;charset=UTF-8")
	public Flux<String> chooseModelThinking(@RequestParam(value = "userInput", defaultValue = "你是谁?") String userInput,
			@RequestParam(value = "model", defaultValue = "qwen-plus") String model) {
		return this.chatClient.prompt()
			.options(DashScopeChatOptions.builder().withModel(model).withEnableThinking(true).build())
			.user(userInput)
			.stream()
			.content();
	}

	@GetMapping(path = "/internet-search", produces = "text/html;charset=utf-8")
	public Flux<String> internetSearch() {
		return this.chatClient.prompt()
			.options(DashScopeChatOptions.builder()
				.withModel(DashScopeApi.ChatModel.QWEN_PLUS.getModel())
				.withEnableSearch(Boolean.TRUE)
				.withStream(Boolean.TRUE)
				.build())
			.advisors(new ReasoningContentAdvisor())
			.user("查询一下杭州今天的天气")
			.stream()
			.content();
	}

	@GetMapping(path = "/prompt", produces = "text/html;charset=UTF-8")
	public Flux<String> prompt(@RequestParam(value = "name", defaultValue = "xu-ai智能助手") String name,
			@RequestParam(value = "voice", defaultValue = "幽默") String voice) {
		String userText = """
				告诉我海盗黄金时代的三位著名海盗以及他们这样做的原因。
				至少为每个海盗写一句话。
				""";
		Message userMessage = new UserMessage(userText);

		String systemText = """
				您是一个有用的人工智能助手，可以帮助人们查找信息。
				你的名字是 {name},
				您应该使用你的姓名并以 {voice} 的风格回复用户的请求。
				""";
		SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemText);
		Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", name, "voice", voice));

		Prompt prompt = new Prompt(List.of(userMessage, systemMessage));

		return this.chatClient.prompt(prompt).user(userText).stream().content();
	}

	@GetMapping(path = "/chat-memory", produces = "text/html;charset=UTF-8")
	public Flux<String> chatMemory(@RequestParam(value = "userInput", defaultValue = "你是谁?") String userInput,
			@RequestParam(value = "chatId", defaultValue = ChatMemory.DEFAULT_CONVERSATION_ID) String chatId) {
		return this.chatClient.prompt()
			.user(userInput)
			.advisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
			.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, chatId))
			.stream()
			.content();
	}

	@GetMapping(path = "/query-answer-rag", produces = "text/html;charset=UTF-8")
	public Flux<String> queryAnswerRag(@RequestParam(value = "userInput", defaultValue = "你是谁?") String userInput) {
		return this.chatClient.prompt()
			.user(userInput)
			.advisors(QuestionAnswerAdvisor.builder(vectorStore).build())
			.stream()
			.content();
	}

	@GetMapping(path = "/document-retriever-rag", produces = "text/html;charset=UTF-8")
	public Flux<String> documentRetrieverRag(
			@RequestParam(value = "userInput", defaultValue = "你是谁?") String userInput) {
		return this.chatClient.prompt()
			.user(userInput)
			.advisors(RetrievalAugmentationAdvisor.builder()
				.documentRetriever(VectorStoreDocumentRetriever.builder()
					.vectorStore(vectorStore)
					.similarityThreshold(0.5d)
					.topK(3)
					.build())
				.build())
			.stream()
			.content();
	}

	@GetMapping(path = "/chat-memory-rag", produces = "text/html;charset=UTF-8")
	public Flux<String> chatMemoryRag(@RequestParam(value = "userInput", defaultValue = "你是谁?") String userInput,
			@RequestParam(value = "chatId", defaultValue = ChatMemory.DEFAULT_CONVERSATION_ID) String chatId) {
		return this.chatClient.prompt()
			.user(userInput)
			.advisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
			.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, chatId))
			.advisors(RetrievalAugmentationAdvisor.builder()
				.documentRetriever(VectorStoreDocumentRetriever.builder()
					.vectorStore(vectorStore)
					.similarityThreshold(0.5d)
					.topK(3)
					.build())
				.build())
			.stream()
			.content();
	}

	@GetMapping(path = "/tool", produces = "text/html;charset=UTF-8")
	public Flux<String> tool(@RequestParam(value = "userInput", defaultValue = "当前时间是多少") String userInput) {
		return this.chatClient.prompt().user(userInput).tools(dateTimeTool).stream().content();
	}

}
